package com.jrx.anytxn.customer.controller;

import com.jrx.anytxn.common.constant.Constants;
import com.jrx.anytxn.common.data.BusinessRes;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.SeqUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.customer.config.CouponConfig;
import com.jrx.anytxn.customer.config.TemplatePathConfig;
import com.jrx.anytxn.customer.constant.CouponConstant;
import com.jrx.anytxn.customer.constant.CustomerConstant;
import com.jrx.anytxn.customer.dto.BaseApiReq;
import com.jrx.anytxn.customer.dto.coupon.CouponReq;
import com.jrx.anytxn.customer.entity.CmCustomerRightInfo;
import com.jrx.anytxn.customer.entity.CmCustomerSecondLevel;
import com.jrx.anytxn.customer.entity.TlCouponDetail;
import com.jrx.anytxn.customer.entity.TlRightsExchangeLog;
import com.jrx.anytxn.customer.service.ICouponInputService;
import com.jrx.anytxn.customer.service.ICouponMeaasgeService;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.customer.service.IRightsExchangeLogService;
import com.jrx.anytxn.customer.util.ReadCsvUtil;
import com.jrx.anytxn.feign.transaction.request.SendSmsReq;
import com.jrx.anytxn.feign.transaction.service.IAnyTxnTransactionService;
import com.jrx.anytxn.i18n.response.TxnRespResult;
import com.jrx.anytxn.param.dto.rights.CardCouponDetailRes;
import com.jrx.anytxn.param.dto.rights.PrRightsQualificationRes;
import com.jrx.anytxn.param.entity.PrCodeTable;
import com.jrx.anytxn.param.entity.PrRightsAndInterestsRes;
import com.jrx.anytxn.param.mapper.ext.ExtPrCodeTableMapper;
import com.jrx.anytxn.param.service.rights.IPrRightsAndInterestsService;
import com.jrx.anytxn.param.service.rights.IPrRightsQualificationService;
import com.jrx.anytxn.param.utils.BizTypeProducts;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author lbz date 2020/8/27
 * @ClassName CouponController 优惠券类接口
 **/
@Api(tags = "优惠券发放")
@RestController
@RequestMapping(value = "/api/customer/coupon")
public class CouponController {
    private static final Logger logger = LoggerFactory.getLogger(CouponController.class);

    @Autowired
    private ICouponInputService couponInputService;
    @Autowired
    private TemplatePathConfig templatePathConfig;
    @Autowired
    private ICouponMeaasgeService couponMessageService;
    @Autowired
    private IPrRightsQualificationService prRightsQualificationService;
    @Autowired
    private IPrRightsAndInterestsService rightsAndInterestsService;
    @Autowired
    private CouponConfig couponConfig;
    @Autowired
    private ICustomerService customerService;
    @Autowired
    private IRightsExchangeLogService rightsExchangeLogService;
    @Lazy
    @Autowired
    private IAnyTxnTransactionService anyTxnTransactionService;
    @Resource
    private ExtPrCodeTableMapper extPrCodeTableMapper;

    @ApiOperation(value = "优惠券发放上传", notes = "优惠券发放上传")
    @PostMapping(value = "/upload")
    public TxnRespResult<String> couponUpload(@RequestParam("file") MultipartFile upfile, @RequestParam String tenantId,
        @RequestParam String userName) throws Exception {
        TxnRespResult<String> result = new TxnRespResult<>();
        logger.info("优惠券发放开始:startTime:{}", result.getStartTime());
        try {
            byte[] bate = upfile.getBytes();
            // 读取CSV文件
            List<Map<String, Object>> list = ReadCsvUtil.getResource(bate);
            if (list != null) {
                couponInputService.couponInput(list, tenantId, userName, upfile.getOriginalFilename());
            }
            String resultMessage = "success";
            result.getSuccess(resultMessage);
        } catch (TxnException e) {
            logger.error("优惠券发放上传异常", e);
            couponMessageService.buildCouponSummary(0L, tenantId, CustomerConstant.DEFAULT_ORG_ID,
                upfile.getOriginalFilename(), 0, CustomerConstant.FAIL, userName);
            result.getFail(e.getErrCode(), e.getMessage());
        }
        logger.debug("优惠券发放结束endTime{}", result.getEndTime());
        return result;
    }

    @ApiOperation(value = "下载优惠券模板", notes = "下载优惠券模板")
    @GetMapping(value = "/downLoad")
    public void downLoadCoupon(HttpServletResponse response, @RequestParam("filePath") String filePath,
        @RequestParam String tenantId) {
        String templatePath = templatePathConfig.getTemplatePath() + "/" + tenantId + "/";
        logger.info("下载优惠券模板地址：{}", templatePath);
        response.setContentType("application/csv");
        File file = new File(templatePath + filePath);
        try (FileInputStream fileInputStream = new FileInputStream(file);
            OutputStream outputStream = response.getOutputStream();) {
            IOUtils.write(IOUtils.toByteArray(fileInputStream), outputStream);
            response.setHeader("Content-Disposition", "inline; filename= couponTemplate.csv");
            outputStream.flush();
        } catch (Exception e) {
            logger.error("下载优惠券模板异常", e);
        }
    }

    /**
     * 权益发放
     * 
     * @param couponReq
     * @return
     */
    @ApiOperation(value = "权益发放", notes = "权益发放")
    @PostMapping(value = "/grant")
    public TxnRespResult<List<TlCouponDetail>> grantCoupon(@RequestBody CouponReq couponReq) {
        TxnRespResult<List<TlCouponDetail>> result = new TxnRespResult<>();
        logger.info("优惠券发放开始:startTime:{}", result.getStartTime());
        try {
            result.getSuccess(couponInputService.grantCoupon(couponReq));
        } catch (TxnException txnException) {
            logger.error("权益发放失败：", txnException);
            result.getFail(txnException.getErrCode(), txnException.getMessage());
        }
        logger.debug("优惠券发放结束:endTime{}", result.getEndTime());
        return result;
    }

    @ApiOperation(value = "兑换权益资格",notes = "兑换权益资格")
    @PostMapping(value = "/exchangeQualification")
    public TxnRespResult<CmCustomerRightInfo> exchangeQualification(@RequestBody CouponReq couponReq) throws Exception {
        TxnRespResult<CmCustomerRightInfo> result = new TxnRespResult<>();

        //提前兑换标记
        boolean advanceExchange = false;
        // 默认值为每月25号10点30分
        Integer limitDay = 25;
        int limitHour = 10;
        int limitMinute = 30;
        try {
            PrCodeTable prCodeTable = extPrCodeTableMapper.selectByTypeIdAndCodeId("EXCHANGE_TIME", "exchangeTime", couponReq.getTenantId());
            if (Objects.nonNull(prCodeTable)) {
                String[] periods = prCodeTable.getCodeName().split("-");
                if (periods.length == 3) {
                    // 每月几号
                    limitDay = Integer.valueOf(periods[0]);
                    // 几点
                    limitHour = Integer.parseInt(periods[1]);
                    // 几分
                    limitMinute = Integer.parseInt(periods[2]);
                }
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            logger.warn("解析权益兑换的日-时-分段出错：{}", e);
        }

        Integer dayOfMonth = DateUtils.getCurrentDayOfMonth();
        if (limitDay.compareTo(dayOfMonth) > 0) {
            advanceExchange = true;
        }
        if (limitDay.compareTo(dayOfMonth) == 0) {
            //当前时间
            Calendar currentTime = Calendar.getInstance();
            int hour = currentTime.get(Calendar.HOUR_OF_DAY);
            int minute = currentTime.get(Calendar.MINUTE);
            //早于10点30分
            if (hour < limitHour || (hour == limitHour && minute < limitMinute)) {
                advanceExchange = true;
            }
        }

        //判断当前时间是否在每月25号10.30之前
        if (advanceExchange) {
            String errMsg = TxnRespCode.EXCHANGE_ACTIVITY_NOT_BEGIN.getFormatMsg(limitDay + "号" + limitHour + ":" +  (limitMinute < 10 ? "0" + limitMinute : limitMinute));
            logger.info(errMsg);
            return result.getFail(TxnRespCode.EXCHANGE_ACTIVITY_NOT_BEGIN.getCode(), errMsg);
        }

        try {
            CmCustomerRightInfo cmCustomerRightInfo = couponInputService.exchangeQualification(couponReq);
            result.getSuccess(cmCustomerRightInfo);

            TlRightsExchangeLog thisExchangeLog = rightsExchangeLogService.findByIdAndCustomer(cmCustomerRightInfo.getRightsExchangeLogId(), cmCustomerRightInfo.getCustomerId(), cmCustomerRightInfo.getTenantId(), cmCustomerRightInfo.getChannel());
            if (thisExchangeLog != null && StringUtils.isNotBlank(thisExchangeLog.getCardPassword())) {//只有客户兑换卡密权益时才发送短息
                logger.info("----兑换的权益为卡密商品----");
                CmCustomerSecondLevel customerSecondLevel = customerService.getSecondByChannelAndCustomerIdAndTensnId(Constants.DEFAULT_CHANNEL,
                        cmCustomerRightInfo.getCustomerId(),cmCustomerRightInfo.getTenantId(), null);
                String rightName = thisExchangeLog.getCouponName();
                String cardPassword = thisExchangeLog.getCardPassword();
                generalSendSms(customerSecondLevel,CouponConstant.SMS_TYPE_EXCHANGE_RIGHTS,rightName+"---"+cardPassword);
            }
        } catch (TxnBizException txnBizException) {
            logger.warn("兑换权益资格失败", txnBizException);
            result.getFail(txnBizException.getErrCode(), txnBizException.getMessage());
        }
        return result;
    }

    @ApiOperation(value = "订单详情-卡券信息",notes = "订单详情-卡券信息")
    @PostMapping(value = "/cardCouponDetail")
    public TxnRespResult<CardCouponDetailRes> cardCouponDetail(@RequestBody CouponReq couponReq){
        TxnRespResult<CardCouponDetailRes> result = new TxnRespResult<>();
        logger.info("订单详情-卡券信息开始:startTime:{}", result.getStartTime());
        try {
            result.getSuccess(couponInputService.cardCouponDetail(couponReq));
        }catch (TxnException txnBizException){
            logger.error("订单详情-卡券信息失败：", txnBizException);
            result.getFail(txnBizException.getErrCode(), txnBizException.getMessage());
        }
        logger.debug("订单详情-卡券信息结束:endTime{}", result.getEndTime());
        return result;
    }

    @ApiOperation(value = "获取权益资格详情", notes = "获取权益资格详情")
    @PostMapping(value = "/qualificationDetail")
    public TxnRespResult<PrRightsQualificationRes> qualificationDetail(@RequestBody CouponReq couponReq) {
        TxnRespResult<PrRightsQualificationRes> result = new TxnRespResult<>();
        PrRightsQualificationRes res = prRightsQualificationService.getDetailByTenantIdAndQuaId(couponReq.getTenantId(), couponReq.getRightsQualificationId());
        result.getSuccess(res);
        return result;
    }

    /**
     * 获取权益参数表
     * @param baseApiReq
     * @return
     */
    @ApiOperation(value = "获取所有权益参数信息", notes = "获取所有权益参数信息")
    @PostMapping(value = "/listRightsAndInterests")
    public TxnRespResult<List<PrRightsAndInterestsRes>> listRightsAndInterests(@RequestBody BaseApiReq baseApiReq){
        TxnRespResult<List<PrRightsAndInterestsRes>> result = new TxnRespResult<>();
        result.getSuccess(rightsAndInterestsService.findAllByTenId(baseApiReq.getTenantId()));
        return result;
    }

    @ApiOperation(value = "新用户激活送120元券活动", notes = "新用户激活送120元券活动")
    @PostMapping(value = "/activityActive120YuanMonthsly")
    public TxnRespResult<BusinessRes> activityActive120YuanMonthsly(@RequestBody CouponReq couponReq) throws Exception {
        TxnRespResult<BusinessRes> result = new TxnRespResult<>();
        CmCustomerSecondLevel customerSecondLevel = customerService.getSecondLevelByCondition(couponReq.getUserId(),
                couponReq.getChannel(), couponReq.getTenantId(), null);
        String activityIds = null;
        try {//设置默认活动Id
            activityIds = couponConfig.getChannelMissing();
            String subChannel = couponReq.getSubChannel();
            if (StringUtils.isNotBlank(subChannel) && couponConfig.getCompatibleChannels().contains(subChannel)){
                logger.info("不与MGM互斥的渠道");
                String activityId = couponConfig.getChannels().get(subChannel);
                if (!StringUtils.isBlank(activityId)){
                    activityIds = activityId;
                }
            }
            //有推荐人编号--通过邀新渠道激活
            else if (StringUtils.isNotBlank(customerSecondLevel.getRecommenderCode())){
                logger.info("有推荐人编号,通过邀新渠道激活");
                activityIds = couponConfig.getMGM();
            }
            else if(!StringUtils.isBlank(subChannel)){
                String activityId = couponConfig.getChannels().get(subChannel);
                if (!StringUtils.isBlank(activityId)){
                    activityIds = activityId;
                }
            }
            String[] activityIdsArr = activityIds.split(",");
            for (String activityId : activityIdsArr) {
                logger.info("开始处理发券逻辑");
                couponReq.setActivityId(activityId);
                couponInputService.grantCoupon(couponReq);
            }
            //发送短信
            generalSendSms(customerSecondLevel,CouponConstant.SMS_TYPE_GRANT_COUPON_RIGHTS,CouponConstant.MORE_COUPON_END_FIX);

        } catch (TxnException txnException) {
            logger.error("发放新人礼失败：",txnException);
            return result.getFail(txnException.getErrCode(), txnException.getErrMsg());
        }
        return result.getSuccess(null);
    }

    private void generalSendSms(CmCustomerSecondLevel customerSecondLevel, String smsType, String rightsName){
        logger.info("组装发送短信的必要参数");
        SendSmsReq req = new SendSmsReq();
        req.setCustomerId(customerSecondLevel.getCustomerId());
        req.setChannel(customerSecondLevel.getChannel());
        req.setTenantId(customerSecondLevel.getTenantId());
        req.setMobile(customerSecondLevel.getMobile());
        req.setSeqNo(SeqUtils.getRandomNumber(18));
        req.setSmsType(smsType);
        req.setLoanId(rightsName);
        anyTxnTransactionService.sendSms(req);
    }

    @ApiOperation(value = "根据产品发送优惠券", notes = "根据产品发送优惠券")
    @PostMapping(value = "/sendCouponByProductId")
    public TxnRespResult<BusinessRes> sendCouponByProductId(@RequestBody CouponReq couponReq) throws Exception {
        CmCustomerSecondLevel customerSecondLevel = customerService.getSecondLevelByCondition(couponReq.getUserId(),
                couponReq.getChannel(), couponReq.getTenantId(), null);

        if (Objects.isNull(customerSecondLevel)) {
            throw new TxnBizException("客户信息不存在");
        }

        Map<String, String> activityMap = couponConfig.getProductId();

        String activityIds = activityMap.get(couponReq.getProductCode());

        if (StringUtils.isBlank(activityIds)) {
            throw new TxnBizException("活动信息不存在");
        }

        String[] activityIdsArr = activityIds.split(",");
        for (String activityId : activityIdsArr) {
            logger.info("开始处理发券逻辑");
            couponReq.setActivityId(activityId);
            couponInputService.grantCoupon(couponReq);
        }

        if (!BizTypeProducts.PRODUCT_XYJY.equals(couponReq.getProductCode())) {
            //信用就医不发送短信
            generalSendSms(customerSecondLevel, CouponConstant.SMS_TYPE_GRANT_COUPON_RIGHTS, CouponConstant.MORE_COUPON_END_FIX);
        }
        return new TxnRespResult<BusinessRes>().getSuccess(null);
    }
}
